﻿
/*-------------------------------------------------
 *  
 * LiMeLanguage MainCode.
 * Latest Update 2011-05-02.
 * 
 * ...コメント処理の実装終了。
 * ...関数ごとに文をclassに分ける？
 * ...上記の案は決定事項なので、classの実装をする。
 * ...classの実装終了。
 * ...文法を明確に定義し、最適化処理を書く。
 * 
 * Edit By Swallow.
 * 
---------------------------------------------------*/



using System;
using System.Data;
using System.Collections.Generic;
using System.Text.RegularExpressions;


#region テスト呼び出し
class Test
{
    static public void Main()
    {
        using (System.IO.StreamReader sr = new System.IO.StreamReader("test.ltm"))
        {
            LiMeLanguage tm = new LiMeLanguage(sr.ReadToEnd());

            Console.WriteLine("\nProcces Start... Press Any Key");
            Console.Read();

            tm.MainProc();

            Console.WriteLine("\nProcces End... Press Any Key");
            Console.Read();
        }
    }
}
#endregion



class LiMeLanguage
{
    #region コード系変数
    private string Code = "";//コード。こいつに最適化処理がコンストラクタでなされる。
    string[] SpaceSplit;//空白で分割したToken. Codeから分割される。
    private List<Expression> CodeTokens = new List<Expression>(); //文の区切りのList。SpaceSplitから文毎に分けられる。
    private List<Functions> CodeFunctions = new List<Functions>();//関数リスト。CodeTokensから関数別にリストに入る。
    private List<Class> CodeClass = new List<Class>();//クラスのリスト。コードの変数宣言と、CodeFunctionsからリストに入る。
    #endregion

    #region コンストラクタ&コメント処理
    public LiMeLanguage(string SourceCode)
    {

        Literal.Move(ref Code);//リテラルの移動


        Code = SourceCode.Replace("\t", " ");//タブ文字を削除
        Code = Regex.Replace(Code, "[ ]+", " ");//余分な空白の削除
        Init.Comment.DeleteComment(ref Code);//コメントの消去
        Code = Code.Replace(Environment.NewLine, "");//改行の削除

        Optimization.Proc(ref Code);//最適化処理

        Init.GetClass.GetClassMember(ref Code, ref CodeClass);//クラス処理

        SpaceSplit = Code.Split(' ');//空白で切り分ける。


        Literal.Undo(ref SpaceSplit);//リテラルの復元

        #region debug
#if DEBUG
        Console.Write("\n[InputCode-Optimization]");
        foreach (string temp in SpaceSplit)
        {
            Console.Write(" " + temp);
        }
#endif
        #endregion
    }

    
    #endregion

    #region Core(各関数呼び出し)
    public void MainProc()
    {
        if (Code == null){throw new NotCodeException("コードが空です。"); }
        SyntaxError.Init();
        this.Parse();
    }
    #endregion

    #region 構文解析
    private void Parse()
    {

        Split.Expressions.Split(ref Code, ref CodeTokens, SpaceSplit);// 文ごとにCodeTokensのListに入れる

        #region debug
#if DEBUG
        /*Debug*/
        Console.WriteLine("[Queue::Parse::Split::Step1]");
        int co = 0;
        foreach (Expression e in CodeTokens)
        {
            Console.WriteLine("\t[{0} - TokenList]", co);
            string[] debug = e.TokenList.ToArray();
            foreach (string d in debug)
            {
                Console.Write("\t\t" + d + "\n");
            }
            co++;
        }
#endif
        #endregion

        Split.AtMark.Split(ref CodeTokens);//アットマークの切り分け(関数宣言記号)

        #region debug
#if DEBUG
        /*Debug*/
        Console.WriteLine("[Queue::Parse::Split::Step2]");
        int cosss = 0;
        foreach (Expression e in CodeTokens)
        {
            Console.WriteLine("\t[{0} - TokenList]", cosss);
            string[] debug = e.TokenList.ToArray();
            foreach (string d in debug)
            {
                Console.Write("\t\t" + d + "\n");
            }
            cosss++;
        }
#endif
        #endregion

        Split.Dollar.Split(ref CodeTokens);//ドルマークの切り分け(関数呼び出し記号)

        #region debug
        #if DEBUG
        Console.WriteLine("[Queue::Parse::Split::Step3]");
        cosss = 0;
        foreach (Expression e in CodeTokens)
        {
            Console.WriteLine("\t[{0} - TokenList]", cosss);
            string[] debug = e.TokenList.ToArray();
            foreach (string d in debug)
            {
                Console.Write("\t\t" + d + "\n");
            }
            cosss++;
        }
#endif
        #endregion

        Split.Function.Split(ref CodeFunctions, CodeTokens);//関数別に分ける
        Split.Args.Split(ref CodeFunctions);
        #region debug
#if DEBUG
        Console.WriteLine("[Queue::Parse::Split::Step4]");
        cosss = 0;
        foreach (Functions e in CodeFunctions)
        {
            Console.WriteLine("Name = " +e.Name);
            Console.WriteLine("Class = " + e.Class);
            Console.WriteLine("Access = " + e.AccessLevel);
            Console.Write("Args = ");
            foreach (string exp in e.ArgName.ToArray())
            {
                Console.WriteLine("\t" + exp);
            }

            string[] temp = e.Expression.ToArray();
            Console.Write("Main = ");
                foreach (string aaa in temp)
                {
                    Console.WriteLine("\t"+aaa);
                }

        }
#endif
        #endregion

        Split.Classer.Split(ref CodeClass, CodeFunctions);//クラス別に分ける

        #region debug
#if DEBUG
        Console.WriteLine("[Queue::Parse::Split::Step5]\n");

        foreach (Class c in CodeClass)
        {
            Console.WriteLine("ClassName = " + c.Name);
            Console.WriteLine("Static = "+c.StaticSign.ToString());

            foreach (Functions f in c.Functions)
            {
                Console.WriteLine("\tFuncName = " + f.Name);
                Console.WriteLine("\tAccessLevel = " + f.AccessLevel);
                foreach (string s in f.Expression)
                {
                    Console.WriteLine("\t\t" + s);
                }
                Console.WriteLine("");
            }
            Console.WriteLine("");
        }
#endif
        #endregion

    }
    #endregion

}
